package generate;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;

import compare.DiffHandleUtils;
import decomplier.Decomplier;
import decomplier.UnzipJar;
import file.WriteFile;
import method.ParseJavaMethod;

/**
 * 完整业务入口
 * 1、反编译jar
 * 2、解压反编译后的Jar包
 * 3、解析反编译后的java文件为具体的方法
 * 4、生成对比文件
 */
public class GenerateFile {
	//解压后的文件后缀
	public final String _unzip = "_unzip";
	//生成方法文件的扩展名
	public final String methodSuffix = ".txt";
	//生成的文件目录
	public final String createFileDir = "compare";
	//方法内容目录
	String methodPrefix = "^METHOD^";
	//html的后缀
	public final String htmlSuffix = ".html";
	//随机数生成
	Random random = new Random();
	/**
	 * 反编译后方法内容生成单独文件
	 */
	public void generateMethonContentFile(String jarPath, String jarName) {
		String projectPath = System.getProperty("user.dir");
		String outPathUse = projectPath + File.separator + createFileDir + File.separator + jarPath;
		File outPathFile = new File(outPathUse);
		if(!outPathFile.exists()) {
			outPathFile.mkdir();
		}
		jarPath = jarPath + File.separator + jarName;
		UnzipJar unzip = new UnzipJar();
		String unzipName = jarName.split("\\.")[0] + _unzip;
		String unzipJarPath = outPathUse + "/" + jarName;
		//解压后输入的目录地址
		String unzipOutPath = outPathUse + "/" + unzipName;
		File unzipOutFile = new File(unzipOutPath);
		if(!unzipOutFile.exists()) {
			Decomplier complier = new Decomplier();
			complier.exeDecomplier(jarPath, outPathUse);
			System.out.println("反编译完成");
			try {
				//解压jar包 
				unzip.unzipJar(unzipOutPath, unzipJarPath);
				System.out.println("解压缩完成");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		//遍历反编译后的目录，获取所有java文件
		List<File> allJavaList = getAllFilesByRecursion(unzipOutFile);
		//转换对象
		ParseJavaMethod parse = new ParseJavaMethod();
		//写入对象
		WriteFile write = new WriteFile();
		//遍历java文件目录,逐个类生成method内容文件
		for(File file: allJavaList) {
			String className = file.getName();
	    	String splitNames[] = file.getAbsolutePath().split(_unzip);
	    	String packName = splitNames[1].replaceAll("\\\\", "\\.");
	    	if(packName.startsWith(".")) {
	    		packName = packName.replaceFirst("\\.", "");
	    	}
	    	String sourceName = packName.replace(".java", "");
	    	String javaClassName = className.replace(".java", "");
	    	//截取类所在的目录地址
	    	String fileDir = file.getAbsolutePath().replace(className, "");
			List<JavaMethod> methodList = parse.getMethInfo(file.getAbsolutePath(), sourceName);
			for(JavaMethod method : methodList) {
				StringBuilder suffix = new StringBuilder("^");
				for(JavaParameter parameter : method.getParameters()) {
					String paramTypeName = parameter.getCanonicalName();
					//截取掉包名称，减少字符长度
					String[] paramNames = paramTypeName.split("\\.");
					suffix.append(paramNames[paramNames.length - 1]).append("^");
				}
				//没有后缀的文件名称
				String methodFileNameNoSuffix = javaClassName + methodPrefix + method.getName() + suffix; 
				if(methodFileNameNoSuffix.length() > 255) {
					methodFileNameNoSuffix = methodFileNameNoSuffix.substring(250);
				}
				String methodFileName = methodFileNameNoSuffix + methodSuffix;
				//单个方法生成的地址
				String methodPath = fileDir + File.separator + methodFileName;
				File methodPathFile = new File(methodPath);
				if(methodPathFile.exists()) {
					try {
						int randomNumber = random.nextInt(9000) + 1000;
						methodPath = methodPath + randomNumber;
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				String codeContent = method.getCodeBlock();
				try {
					write.write(methodPath, codeContent);
				}catch (Exception e2) {
					e2.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 比较两个文件，生成差异文件
	 * @param jarPathMain
	 * @param jarPathSlave
	 */
	public void compareDiffMethodFile(String jarPathMain, String jarPathSlave) {
		String projectPath = System.getProperty("user.dir");
		//主对比文件
		String mainVesionPath = projectPath + File.separator + createFileDir + File.separator + jarPathMain;
		//次对比文件
		String slaveVersionPath = projectPath + File.separator + createFileDir + File.separator + jarPathSlave;
		//主要文件目录
		File mainFileDir = new File(mainVesionPath);
		//遍历反编译后的目录，获取所有java文件
		List<File> allJavaList = getAllFilesByRecursion(mainFileDir);
		//遍历java文件目录,逐个类生成method内容文件
		for(File file: allJavaList) {
			String filePathName = file.getAbsolutePath();
			//过滤出来非方法内容的文件
			if(filePathName.contains(methodPrefix) && !filePathName.contains(htmlSuffix)) {
				int position = 0;
				position = filePathName.indexOf(methodSuffix);
				//生成的html文件
				String filePathNoSuffix = filePathName.substring(0, position);
				String filePathHtml = filePathNoSuffix + htmlSuffix;
				//获取所在目录
				position = filePathName.indexOf(file.getName());
				String fileDir = filePathName.substring(0, position);
				//获取class文件的Pack名称
		    	String splitNames[] = filePathName.split(_unzip);
		    	String packName = splitNames[1];
				String slavePath = slaveVersionPath + File.separator + packName;
				try {
					//对比两个文件
					List<String> diffString = DiffHandleUtils.
							diffString(filePathName,slavePath);
					//在F盘生成一个diff.html文件，打开便可看到两个文件的对比
					DiffHandleUtils.generateDiffHtml(diffString, filePathHtml);
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		

	}
	
	/**
	 * 遍历指定目录
	 * @param dir
	 * @return
	 */
	public List<File> getAllFilesByRecursion(File dir) {
	  List<File> fileList = new ArrayList<>();
	  File[] files = dir.listFiles();
	  for (File file : files) {
	      if (file.isDirectory()) {
	    	  //是目录就继续遍历
	          fileList.addAll(getAllFilesByRecursion(file));
	      } else {
	          fileList.add(file);
	      }
	  }
	  return fileList;
	}
	
	public static void main(String[] args) {
		GenerateFile generate = new GenerateFile();
//		String jarName = "rt_fix_gateway.jar";
//		String jarPath = "othersPoject_libs/10.5/" ;
//		//反编译并且抽取method内容单独生成文件
//		generate.generateMethonContentFile(jarPath, jarName);
//		
//		String jarName2 = "rt_fix_gateway.jar";
//		String jarPath2 = "othersPoject_libs/23.1/" ;
//		//反编译并且抽取method内容单独生成文件
//		generate.generateMethonContentFile(jarPath2, jarName2);
		
		//生成对比文件
		String salveStr = "othersPoject_libs\\10.5\\rt_fix_gateway_unzip";
		String mainStr = "othersPoject_libs\\23.1\\rt_fix_gateway_unzip";
		generate.compareDiffMethodFile(mainStr, salveStr);
	}
}
